package com.gaofans.nrpc.common.serializer.kryo;

import com.esotericsoftware.kryo.Kryo;
import com.esotericsoftware.kryo.io.Input;
import com.esotericsoftware.kryo.io.Output;
import com.esotericsoftware.kryo.util.Pool;
import com.gaofans.nrpc.common.exception.NRpcException;
import com.gaofans.nrpc.common.serializer.Serializer;
import com.gaofans.nrpc.common.serializer.SerializerExceptionEnum;

/**
 * @author GaoFans
 */
public class KryoSerializer implements Serializer {

    private Pool<Kryo> kPool;
    private Pool<Output> oPool;
    private Pool<Input> iPool;

    public KryoSerializer(Pool<Kryo> kPool, Pool<Output> oPool, Pool<Input> iPool) {
        this.kPool = kPool;
        this.oPool = oPool;
        this.iPool = iPool;
    }

    @Override
    public <T> byte[] serialize(T t) {
        Kryo kryo = kPool.obtain();
        Output output = oPool.obtain();
        try {
            output.reset();
            kryo.writeObject(output,t);
        }catch (Exception e){
            throw new NRpcException(e.getCause(),SerializerExceptionEnum.SerializerException);
        }finally {
            kPool.free(kryo);
            oPool.free(output);
        }
        return output.getBuffer();
    }

    @Override
    public <T> T deserialize(byte[] bytes, Class<T> clazz) {
        Kryo kryo = kPool.obtain();
        Input input = iPool.obtain();
        try {
            input.setBuffer(bytes);
            return kryo.readObject(input,clazz);
        }catch (Exception e){
            throw new NRpcException(e.getCause(),SerializerExceptionEnum.DeSerializerException);
        }finally {
            kPool.free(kryo);
            iPool.free(input);
        }
    }
}
